using System;
using NUnit.Framework;
using ValidationFramework;
using ValidationFramework.Reflection;

namespace ExampleLibraryCSharp
{
    public class MethodCacheExample
    {
        #region Example
        public class Bike
        {
            public static readonly RuntimeMethodHandle ChangeWheelsMethodHandle =
          typeof(Bike).GetMethod("ChangeWheels").MethodHandle;

            //Assume for the purposes of this sample that a bike can have between 1 
            // and 2 wheels changed at a time.
            public void ChangeWheels(int numberOfWheels)
            {
                ParameterValidationManager.ThrowException(this, ChangeWheelsMethodHandle,
                    numberOfWheels);
                // Business code goes here
            }

        }

        [TestFixture]
        public class ExampleUsage
        {
            [Test]
            public void Run()
            {
                var thrownOnTooFew = false;
                var thrownOnTooMany = false;
                var bike = new Bike();

                // 0 is valid numberOfWheels because there are no validation rules yet.
                bike.ChangeWheels(0);

                var rangeRule = new RangeRule<int>(null, false, 1, 2, true, true);

                var methodDescriptor = MethodCache.GetMethod(
                    Bike.ChangeWheelsMethodHandle);
                var numberOfWheelsParameterDescriptor =
            methodDescriptor.Parameters["numberOfWheels"];
                numberOfWheelsParameterDescriptor.Rules.Add(rangeRule, null);

                // 0 is an invalid numberOfWheels 
                try
                {
                    bike.ChangeWheels(0);
                }
                catch (ArgumentException)
                {
                    thrownOnTooFew = true;
                }

                // 1 and 2 are a valid numberOfWheels 
                bike.ChangeWheels(1);
                bike.ChangeWheels(2);

                // 3 is an invalid numberOfWheels 
                try
                {
                    bike.ChangeWheels(3);
                }
                catch (ArgumentException)
                {
                    thrownOnTooMany = true;
                }

                numberOfWheelsParameterDescriptor.Rules.Clear();

                // 0 is valid numberOfWheels because the validation rule has been removed.
                bike.ChangeWheels(0);

                Assert.IsTrue(thrownOnTooMany);
                Assert.IsTrue(thrownOnTooFew);
            }
        }
        #endregion
    }
}